package com.luomo.java.jvm;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

/**
 * 软引用和弱引用使用场景：
 *
 * 应用需要读取大量的本地图片
 *  如果每次都从硬盘读取则会严重影响性能
 *  如果一次性全部加载到内存中有可能造成内存溢出
 *
 * 这时可以用软引用或弱引用解决问题
 * 设计思路：用一个HashMap来保存图片路径和相应图片对象关联的软引用之间的映射关系，
 *         在内存不足时，JVM会自动回收这些缓存图片对象所占用的空间，从而有效避免OOM的问题
 *         Map<String,SoftReference<BitMap>> imageCache = new Hashtable<>();
 *
 * @author LiuMei
 * @date 2021-04-14.
 */
public class ReferenceDemo {

    public static void main(String[] args) {
//        AbstractQueuedSynchronizer
//        softRefMemoryEnough();
//        softRefMemoryNotEnough();
//        weakRef();
//        weakQueueRef();
        phantomRef();
    }

    /**
     * 强引用
     * 默认支持模式
     */
    public static void strongRef() {
        Object o1 = new Object();
        Object o2 = o1;
        o1 = null;
        System.gc();
        System.out.println(o2);
    }

    /**
     * 软引用
     * 内存够用的时候就保留，不够用就回收
     */
    public static void softRefMemoryEnough() {
        Object o1 = new Object();
        SoftReference<Object> softReference = new SoftReference<>(o1);
        System.out.println(o1);
        System.out.println(softReference.get());
        o1 = null;
        System.gc();
        System.out.println(o1);
        System.out.println(softReference.get());
    }

    /**
     * JVM配置，故意产生大对象并配置小内存，让内存不够用导致OOM，查看软引用回收情况
     * -Xms5m -Xmx5m -XX:+PrintGCDetails
     */
    public static void softRefMemoryNotEnough() {
        Object o1 = new Object();
        SoftReference<Object> softReference = new SoftReference<>(o1);
        System.out.println(o1);
        System.out.println(softReference.get());
        o1 = null;
        System.gc();
        try {
            byte[] bytes = new byte[30 * 1024 * 1024];
        } finally {
            System.out.println(o1);
            //内存不足，被回收
            System.out.println(softReference.get());
        }
    }

    /**
     * 弱引用
     * 只要垃圾回收机制运行，不管JVM内存空间是否足够，都会回收
     */
    public static void weakRef() {
        Object o1 = new Object();
        WeakReference<Object> reference = new WeakReference<>(o1);
        System.out.println(o1);
        System.out.println(reference.get());
        o1 = null;
        System.gc();
        System.out.println(o1);
        System.out.println(reference.get());
    }

    /**
     * 弱引用+引用队列
     * gc后将对象放入引用队列
     */
    public static void weakQueueRef() {
        Object o1 = new Object();
        ReferenceQueue queue = new ReferenceQueue();
        WeakReference<Object> reference = new WeakReference<>(o1,queue);
        System.out.println(o1);
        System.out.println(reference.get());
        System.out.println(queue.poll());
        System.out.println("=======================");
        o1 = null;
        System.gc();
        System.out.println(o1);
        System.out.println(reference.get());
        System.out.println(queue.poll());
//        java.lang.Object@3f99bd52
//        java.lang.Object@3f99bd52
//        null
//                =======================
//        null
//        null
//        java.lang.ref.WeakReference@4f023edb
    }

    /**
     * 虚引用
     *
     */
    public static void phantomRef() {
        Object o1 = new Object();
        ReferenceQueue queue = new ReferenceQueue();
        PhantomReference<Object> reference = new PhantomReference<>(o1,queue);
        System.out.println(o1);
        System.out.println(reference.get());
        System.out.println(queue.poll());
        System.out.println("=======================");
        o1 = null;
        System.gc();
        System.out.println(o1);
        System.out.println(reference.get());
        System.out.println(queue.poll());
//        java.lang.Object@3f99bd52
//        null
//        null
//                =======================
//        null
//        null
//        java.lang.ref.PhantomReference@4f023edb
    }

}
